package com.uziot.bucket.eureka.zuul.router;

import com.uziot.bucket.eureka.dao.GatewayApiDefine;
import com.uziot.bucket.eureka.dao.GatewayApiDefineMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute;
import org.springframework.util.StringUtils;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author shidt
 * @version V1.0
 * @className EventApplication
 * @date 2020-12-15 11:02:07
 * @description 路由刷新服务
 */

public class CustomRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {
    public final static Logger log = LoggerFactory.getLogger(CustomRouteLocator.class);

    private GatewayApiDefineMapper gatewayApiDefineMapper;

    private final ZuulProperties zuulProperties;

    public CustomRouteLocator(String servletPath, ZuulProperties zuulProperties) {
        super(servletPath, zuulProperties);
        this.zuulProperties = zuulProperties;
        log.info("servletPath:{}", servletPath);
    }

    /**
     * 主要执行刷新路由方法
     */
    @Override
    public void refresh() {
        super.doRefresh();
    }

    /**
     * 主加载路由方法
     *
     * @return locateRoutes
     */
    @Override
    protected Map<String, ZuulRoute> locateRoutes() {
        LinkedHashMap<String, ZuulRoute> routesMap = new LinkedHashMap<>();
        //从application.properties中加载路由信息
        routesMap.putAll(super.locateRoutes());
        //从db中加载路由信息
        routesMap.putAll(locateRoutesFromDb());
        //优化一下配置
        LinkedHashMap<String, ZuulRoute> routers = new LinkedHashMap<>();
        routesMap.forEach((path, value) -> {
            path = this.getPathString(path);
            routers.put(path, value);
        });
        return routers;
    }

    /**
     * 从数据库中加载路由信息
     *
     * @return map
     */
    private Map<String, ZuulRoute> locateRoutesFromDb() {
        Map<String, ZuulRoute> routes = new LinkedHashMap<>();
        List<GatewayApiDefine> gatewayApiDefines = gatewayApiDefineMapper.loadAll();
        for (GatewayApiDefine result : gatewayApiDefines) {
            if (StringUtils.isEmpty(result.getPath()) || StringUtils.isEmpty(result.getUrl())) {
                continue;
            }
            ZuulRoute zuulRoute = new ZuulRoute();
            try {
                BeanUtils.copyProperties(result, zuulRoute);
            } catch (Exception e) {
                log.error("=============从数据库加载Zuul网关路由发生错误==============", e);
            }
            routes.put(zuulRoute.getPath(), zuulRoute);
        }
        return routes;
    }

    /**
     * 优化路径转换
     *
     * @param path path
     * @return String
     */
    private String getPathString(String path) {
        if (!path.startsWith("/")) {
            path = "/" + path;
        }
        if (StringUtils.hasText(this.zuulProperties.getPrefix())) {
            path = this.zuulProperties.getPrefix() + path;
            if (!path.startsWith("/")) {
                path = "/" + path;
            }
        }
        return path;
    }

    public void setGatewayApiDefineMapper(GatewayApiDefineMapper gatewayApiDefineMapper) {
        this.gatewayApiDefineMapper = gatewayApiDefineMapper;
    }

}
